package com.sunseen.intelligencebus

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothServerSocket
import android.bluetooth.BluetoothSocket
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.PRIORITY_MIN
import com.sunseen.intelligencebus.home.BusMsgGotEvent
import com.sunseen.intelligencebus.home.SendMsgEvent
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.nio.charset.Charset
import java.util.UUID

class BluetoothMsgService : Service() {


    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "onCreate")
    }

    private var mBluetoothAdapter: BluetoothAdapter? = null

    private val blueToothDevices = arrayListOf<String>()

    private val receiver = BluetoothStateChangeReceiver()

    private fun initReceiver() {
        val filter = IntentFilter()
//        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
//        filter.addAction(BluetoothDevice.ACTION_FOUND)
//        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
//        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED)
//        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
        val mContext = applicationContext
        mContext.registerReceiver(receiver, filter)
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Log.d(TAG, "onStartCommand")
        EventBus.getDefault().register(this)
        val channelId =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel("my_service", "bluetooth Background Service")
            } else {
                // If earlier version channel ID is not used
                // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
                ""
            }

        val notificationBuilder = NotificationCompat.Builder(this, channelId)
        val notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_intelligence_bus_launcher)
            .setContentTitle("蓝牙通讯")
            .setContentText("正在运行")
            .setPriority(PRIORITY_MIN)
            .setCategory(Notification.CATEGORY_SERVICE)
            .build()
        // 参数一：唯一的通知标识；参数二：通知消息。
        startForeground(110, notification)// 开始前台服务
        initReceiver()
        initAcceptThread()
        return super.onStartCommand(intent, flags, startId)
    }


    override fun onDestroy() {
        EventBus.getDefault().unregister(this)
        Log.d(TAG, "onDestroy()")
        stopForeground(true)// 停止前台服务--参数：表示是否移除之前的通知
        if (mBluetoothAdapter != null && mBluetoothAdapter?.isDiscovering() ?: false) run { mBluetoothAdapter?.cancelDiscovery() }
        unregisterReceiver(receiver)
        super.onDestroy()
    }

    companion object {

        private val TAG = "test"
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(channelId: String, channelName: String): String {
        val chan = NotificationChannel(
            channelId,
            channelName, NotificationManager.IMPORTANCE_NONE
        )
        chan.lightColor = Color.BLUE
        chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
        return channelId
    }

    private var acceptThread = AcceptThread()
    private val NAME = "bluetooth_socket"//serverSocket name
    //db764ac8-4b08-7f25-aafe-59d03c27bae3

    private val SeriPort_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")//串口UUID

    private val Local_NetWork_UUID = UUID.fromString("00001115-0000-1000-8000-00805F9B34FB")//局域网UUID

    private inner class AcceptThread internal constructor() : Thread() {
        private var mBluetoothServerSocket: BluetoothServerSocket? = null
        private var bluetoothSocket: BluetoothSocket? = null
        private var inputStream: InputStream? = null
        private var os: OutputStream? = null
        private var isContinue: Boolean = false

        init {
            try {
                mBluetoothServerSocket = mBluetoothAdapter?.listenUsingRfcommWithServiceRecord(NAME, Local_NetWork_UUID)
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }

        override fun run() {
            while (true) {
                try {
                    if (mBluetoothServerSocket == null) {
                        return
                    } else {
                        Log.e(TAG, "run: accept be")
                        bluetoothSocket = mBluetoothServerSocket?.accept()
                        Log.e(TAG, "run: accept")
                        inputStream = bluetoothSocket?.inputStream
                        os = bluetoothSocket?.outputStream
                        isContinue = true
                        while (isContinue) {
                            val buffer = ByteArray(128)
                            var count = inputStream!!.read(buffer)
                            val msg = String(buffer, 0, count, Charset.forName("utf-8"))
                            Log.e(TAG, "got msg $msg")
//                            EventBus.getDefault().post(BusMsgGotEvent(msg))
                        }
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                    isContinue = false
                } finally {
                    try {
                        if (bluetoothSocket != null) {
                            bluetoothSocket!!.close()
                        }
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }

                }

            }
        }
    }

    private fun initAcceptThread() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if (null == mBluetoothAdapter) {
            Toast.makeText(this.applicationContext, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show()
            return
        }
        if (mBluetoothAdapter!!.isEnabled()) {
            mBluetoothAdapter!!.enable()
        }
        val bluetoothDevices = mBluetoothAdapter!!.getBondedDevices()
        if (bluetoothDevices.size > 0) {
            for (bluetoothDevice in bluetoothDevices) {
                Log.e("test", "devices蓝牙名：" + bluetoothDevice.name + "----蓝牙地址：" + bluetoothDevice.address)
                blueToothDevices.add(bluetoothDevice.address)
            }
        }
        acceptThread = AcceptThread()

        acceptThread.start()
    }


    private var mBluetoothSocket: BluetoothSocket? = null//蓝牙客户端
    private var mBluetoothDevice: BluetoothDevice? = null//蓝牙设备
    private var mOutputStream: OutputStream? = null//输出流
    /**
     * 发送信息到另一个蓝牙设备
     *
     * @param address 蓝牙设备地址
     * @param message 信息
     */
    private fun sendMessage(address: String, message: String) {
        try {
            if (mBluetoothAdapter != null) {
                if (mBluetoothAdapter?.isDiscovering() ?: false) {
                    mBluetoothAdapter?.cancelDiscovery()
                }
                Log.e(TAG, "sendMessage: 1")
                if (null == mBluetoothDevice) {
                    mBluetoothDevice = mBluetoothAdapter?.getRemoteDevice(address)
                }
                Log.e(TAG, "sendMessage: 2")

                if (mBluetoothSocket == null) {
                    mBluetoothSocket = mBluetoothDevice?.createRfcommSocketToServiceRecord(Local_NetWork_UUID)
                    mBluetoothSocket?.connect()
                    mOutputStream = mBluetoothSocket?.getOutputStream()
                }
                Log.e(TAG, "sendMessage: 3")

                if (mBluetoothSocket!!.isConnected()) {
                    resetSocket()
                }
                Log.e(TAG, "sendMessage: 4")

                try {
                    mOutputStream?.write(message.toByteArray(charset("utf-8")))
                    Log.e(TAG, "sendMsg" + mBluetoothAdapter?.getName() + ":" + message)
                } catch (e: Exception) {
                    resetSocket()
//                    sendMessage(address, message)
                }
            }

        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    private fun resetSocket() {
        try {
            mBluetoothSocket?.close()
            mBluetoothSocket = mBluetoothDevice?.createRfcommSocketToServiceRecord(Local_NetWork_UUID)
            mBluetoothSocket?.connect()
            mOutputStream = mBluetoothSocket?.getOutputStream()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    @Subscribe(threadMode = ThreadMode.ASYNC)
    fun onSendMsg(event: SendMsgEvent) {
        Log.e(TAG, "sendMsg ${event.msg}")
        if (blueToothDevices.size > 0) {
            for (deviceAddress in blueToothDevices) {
                sendMessage(deviceAddress, event.msg)
            }
        } else {
            Log.e("test", "no address")
        }
    }

    var address = ""
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onConnecttedEvent(event: ConnectedEvent) {
        address = event.address
    }

    override fun onBind(intent: Intent): IBinder? {

        Log.d(TAG, "onBind")

        throw UnsupportedOperationException("Not yet implemented")
    }
}
